/**
 * Copyright (c) 2012 Nokia Corporation. 
 */

package com.nokia.example.tictactoe.connectivity;

import java.io.IOException;

import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;
import javax.microedition.io.DatagramConnection;

/**
 * A server for datagram connections.
 */
public class UdpServer extends Connection {
	// Members
	protected DatagramConnection _udpConnection = null;
	protected Datagram _datagram = null;
	protected Integer _port = null;
	protected String _peerAddress = null;
	
	/**
	 * Constructor.
	 */
	public UdpServer() {
	}
	
	/**
	 * From Connection.
	 */	
	public boolean open(String hostname, Integer port) {
		if (_running) {
			System.out.println("UdpServer::open(): Already open!");
			return false;
		}
		
		setState(CONNECTING);
		_port = port;
		
		new Thread() {
			public void run() {
				log("Udp server started");
				_running = true;
				
				try {
					// Open the connection and start listening for datagrams
					_udpConnection =
							(DatagramConnection)Connector.open("datagram://:"
									+ _port.toString());
					_datagram = _udpConnection.newDatagram(_udpConnection.getNominalLength());
					setState(CONNECTED);
					log("Waiting for datagrams...");
					
					_udpConnection.receive(_datagram);
					_peerAddress = _datagram.getAddress();
					
					System.out.println("UdpServer::run(): Initial datagram received: "
							+ _peerAddress);
					notifyReceived(_datagram.getData());
				}
				catch (IOException e) {
					if (_running) {
						notifyFatalError("UDP server failure: " + e.toString());
						close();
					}
				}
				
				while (_running) {
					try {
						_udpConnection.receive(_datagram);
					}
					catch (IOException e) {
						if (_running) {
							notifyFatalError("UDP server failed: " + e.toString());
							close();
						}
					}
					
					notifyReceived(_datagram.getData());
				}
				
				setState(DISCONNECTING);
				_datagram = null;
				_peerAddress = null;
				
				try {
					if (_udpConnection != null) {
						_udpConnection.close();
					}
				} catch (IOException e) {}
				
				_udpConnection = null;
				setState(NOT_CONNECTED);
			}
		}.start();
		
		return true;
	}

	/**
	 * From Connection.
	 */	
	public synchronized boolean send(byte[] message) {
		if (_udpConnection != null) {
			Datagram datagram = null;
			
			try {
				datagram = _udpConnection.newDatagram(message, message.length);
				_udpConnection.send(datagram);
				return true;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		return false;
	}
	
	/**
	 * From Connection.
	 */
	public synchronized void close() {
		System.out.println("UdpServer::close()");
		_running = false;
		
		if (_udpConnection != null) {
			try {
				_udpConnection.close();
			}
			catch (IOException e) {}
			
			_udpConnection = null;
		}
	}	
	
	/** 
	 * @return The peer address if resolved.
	 */
	public String peerAddress() {
		return _peerAddress;
	}
}
